package cn.funeralobjects.ams.service.impl;

import cn.funeralobjects.ams.entity.*;
import cn.funeralobjects.ams.model.ProductApiAccessDto;
import cn.funeralobjects.ams.repository.EProductApiAccessRepository;
import cn.funeralobjects.ams.service.AccessKeyService;
import cn.funeralobjects.ams.service.ProductApiAccessService;
import cn.funeralobjects.ams.service.ProductApiService;
import cn.funeralobjects.ams.service.ProductResService;
import cn.funeralobjects.common.service.annotataion.CommonRollback;
import cn.funeralobjects.common.service.annotataion.CommonService;
import cn.funeralobjects.util.annotation.ArgHasLength;
import cn.funeralobjects.util.annotation.ArgNotZero;
import cn.funeralobjects.util.annotation.AssertArg;
import com.querydsl.jpa.JPQLQueryFactory;

import javax.annotation.Resource;
import java.util.Optional;

/**
 * @author FuneralObjects
 * Create date: 2020/6/2 6:08 AM
 */
@CommonService
public class ProductApiAccessServiceImpl implements ProductApiAccessService {

    @Resource
    private ProductResService productResService;

    @Resource
    private ProductApiService productApiService;

    @Resource
    private AccessKeyService accessKeyService;

    @Resource
    private EProductApiAccessRepository eProductApiAccessRepository;

    @Resource
    private JPQLQueryFactory jpqlQueryFactory;

    @CommonRollback
    @Override
    public void bindOrUpdateAccessKey(Integer prodResId, Integer prodApiId, Integer accessId) {
        productResService.mustExistsById(prodResId);
        productApiService.mustExistsById(prodApiId);
        accessKeyService.mustExistsById(accessId);
        EAccess eAccess = new EAccess();
        eAccess.setId(accessId);
        eProductApiAccessRepository.save(new EProductApiAccess()
                .setPk(new EProductApiAccessPk().setProdApiId(prodApiId).setProdResId(prodResId))
                .setEAccess(eAccess)
                .setProductApi(new EProductApi().setId(prodApiId))
                .setProductRes(new EProductRes().setId(prodResId))
        );
    }

    @CommonRollback
    @Override
    public void unbindAccessKey(Integer prodResId, Integer prodApiId) {
        productResService.mustExistsById(prodResId);
        productApiService.mustExistsById(prodApiId);
        eProductApiAccessRepository.deleteById(new EProductApiAccessPk().setProdApiId(prodApiId).setProdResId(prodResId));
    }

    @AssertArg
    @Override
    public Optional<ProductApiAccessDto> getProductApiAccessKey(@ArgHasLength String prodResCode, @ArgHasLength String action, @ArgHasLength String version) {
        return Optional.ofNullable(jpqlQueryFactory.select(
                QEProductRes.eProductRes.region.regionId,
                QEAccessKey.eAccessKey.accessKeyId,
                QEAccessKey.eAccessKey.accessKeySecret
        ).from(QEAccessKey.eAccessKey)
                .join(QEProductApiAccess.eProductApiAccess).on(QEProductApiAccess.eProductApiAccess.eAccess.id.eq(QEAccessKey.eAccessKey.accessId))
                .join(QEProductApi.eProductApi).on(QEProductApiAccess.eProductApiAccess.pk.prodApiId.eq(QEProductApi.eProductApi.id))
                .join(QEProductRes.eProductRes).on(QEProductRes.eProductRes.id.eq(QEProductApiAccess.eProductApiAccess.pk.prodResId))
                .join(QEAccess.eAccess).on(QEAccessKey.eAccessKey.accessId.eq(QEAccess.eAccess.id))
                .where(
                        QEAccess.eAccess.delSalt.eq(accessKeyService.getExistsDelSalt())
                                .and(QEProductApi.eProductApi.action.eq(action))
                                .and(QEProductApi.eProductApi.version.eq(version))
                                .and(QEProductRes.eProductRes.code.eq(prodResCode))
                ).fetchOne()).map(tuple -> new ProductApiAccessDto().setAccessKeyId(tuple.get(QEAccessKey.eAccessKey.accessKeyId))
                .setAccessKeySecret(tuple.get(QEAccessKey.eAccessKey.accessKeySecret))
                .setRegionId(tuple.get(QEProductRes.eProductRes.region.regionId)));
    }

    @AssertArg
    @Override
    public Optional<ProductApiAccessDto> getProductApiAccessKey(@ArgNotZero Integer prodResId, @ArgHasLength String action, @ArgHasLength String version) {
        return Optional.ofNullable(jpqlQueryFactory.select(
                QEProductRes.eProductRes.region.regionId,
                QEAccessKey.eAccessKey.accessKeyId,
                QEAccessKey.eAccessKey.accessKeySecret
        ).from(QEAccessKey.eAccessKey)
                .join(QEProductApiAccess.eProductApiAccess).on(QEProductApiAccess.eProductApiAccess.eAccess.id.eq(QEAccessKey.eAccessKey.accessId))
                .join(QEProductApi.eProductApi).on(QEProductApiAccess.eProductApiAccess.pk.prodApiId.eq(QEProductApi.eProductApi.id))
                .join(QEProductRes.eProductRes).on(QEProductRes.eProductRes.id.eq(QEProductApiAccess.eProductApiAccess.pk.prodResId))
                .join(QEAccess.eAccess).on(QEAccessKey.eAccessKey.accessId.eq(QEAccess.eAccess.id))
                .where(
                        QEAccess.eAccess.delSalt.eq(accessKeyService.getExistsDelSalt())
                                .and(QEProductApi.eProductApi.action.eq(action))
                                .and(QEProductApi.eProductApi.version.eq(version))
                                .and(QEProductRes.eProductRes.id.eq(prodResId))
                ).fetchOne()).map(tuple -> new ProductApiAccessDto().setAccessKeyId(tuple.get(QEAccessKey.eAccessKey.accessKeyId))
                .setAccessKeySecret(tuple.get(QEAccessKey.eAccessKey.accessKeySecret))
                .setRegionId(tuple.get(QEProductRes.eProductRes.region.regionId)));
    }
}
